/**
 * Created by jinxs on 14-7-15.
 * 基于easyui.layout源码
 */
(function ($) {
    /**
     * 缓存名称
     * @type {string}
     * @private
     */
    var _cacheName = 'uiLayout';
    var _resizing = false;
    var pal_region = {
        top: 'top',
        bottom: 'bottom',
        right: 'right',
        left: 'left',
        center: 'center'
    };
    /**
     * @class 布局组件
     * @constructor uiLayout
     * @summary 构造函数
     * @param [options] {Object|String} 组件配置参数|要调用的组件方法名
     * @param [param] {Object} 表示要调用的方法的参数
     * @example
     * // 构件组件
     * $('#div').uiLayout({
    *      axis:'h',
    *      onStopDrag: function(e){
    *          alert(this[0]==e.data.target[0]);
    *      }
    * });
     * // 调用组件方法options
     * $('#div').uiLayout("options");
     */
    $.fn.uiLayout = function (options, params) {
        if (typeof options == "string") {
            return $.fn.uiLayout.methods[options](this, params);
        }
        return this.each(function(){
            var me = $(this);
            var cache = me.data(_cacheName);

            options = options || {};
            if (cache) {
                $.extend(cache.options, options);
            } else {
                me.data(_cacheName, {
                    options: $.extend({}, $.fn.uiLayout.defaults, me.parseUIConfig(), options),
                    panels: {center: $(), top: $(), bottom: $(), right: $(), left: $()}
                });
                _init(me);
            }
            _resize(me);
            _collapsePanels(me);
        });
    };
    /**
     * 方法
     * @lends uiLayout.prototype
     */
    $.fn.uiLayout.methods = {
        /**
         * @summary 根据配置重置控件的大小
         * @name uiLayout#resize
         * @function
         * @returns {jQuery} 方法调用者
         */
        resize: function (target) {
            _resize(target);
            return target;
        },
        /**
         * @summary 获得组件的面板对象
         * @name uiLayout#panel
         * @function
         * @param palPosition {Number} 面板位置
         * @returns uiPanel 组件的面板对象
         */
        panel: function (target, palPosition) {
            return $.data(target[0], _cacheName).panels[palPosition];
        },
        /**
         * @summary 折叠组件
         * @name uiLayout#collapse
         * @function
         * @param region {Object} 折叠区域
         * @returns {jQuery} 方法调用者
         */
        collapse: function (target, region) {
            _collapsePanel(target, region);
            return target;
        },
        /**
         * @summary 展开组件
         * @name uiLayout#expand
         * @function
         * @param region {Object} 展开区域
         * @returns {jQuery} 方法调用者
         */
        expand: function (target, region) {
            _expandPanel(target, region);
            return target;
        },
        /**
         * @summary 为组件添加面板对象
         * @name uiLayout#add
         * @function
         * @param palOption {Object} 面板参数
         * @returns {jQuery} 方法调用者
         */
        add: function (target, palOption) {
            _addPanel(target, palOption);
            _resize(target);
            if (target.uiLayout('panel', palOption.region).uiPanel('options').collapsed) {
                _collapsePanel(target, palOption.region, 0);
            }
            return target;
        },
        /**
         * @summary 移除指定的组件的面板对象
         * @name uiLayout#remove
         * @function
         * @param region {String} 方向参数
         * @returns {jQuery} 方法调用者
         * @example
         * $('#divMenu').uiLayout("remove", 'left');
         */
        remove: function (target, region) {
            _remove(target, region);
            _resize(target);
            return target;
        }
    };
    $.fn.uiLayout.defaults = {autoFit: false};

    $.fn.uiLayout.paneldefaults = $.extend({}, $.fn.uiPanel.defaults,
        /**
         * 默认配置
         * @lends uiLayout.prototype
         */
        {
            /**
             * @type String
             * @default null
             * @summary 组件区域
             */
            region: null,
            /**
             * @type Boolean
             * @default true
             * @summary 指示组件是否显示边框
             */
            border: true,
            /**
             * @type Boolean
             * @default false
             * @summary 指示组件是否显示按钮栏
             */
            showBtnBar: false,
            /**
             * @type Boolean
             * @default false
             * @summary 指示组件是否可分割
             */
            split: false,
            /**
             * @type Boolean
             * @default true
             * @summary 指示组件是否可折叠
             */
            collapsible: true,
            /**
             * @type Number
             * @default 30
             * @summary 指示组件可折叠的大小
             */
            collapsedSize: 30,
            /**
             * @type Number
             * @default 10
             * @summary 指示组件的最小宽度
             */
            minWidth: 10,
            /**
             * @type Number
             * @default 10
             * @summary 指示组件的最小高度
             */
            minHeight: 10,
            /**
             * @type Number
             * @default 10000
             * @summary 指示组件的最大宽度
             */
            maxWidth: 10000,
            /**
             * @type Number
             * @default 10000
             * @summary 指示组件的最大高度
             */
            maxHeight: 10000
        });

    var _init = function (target) {
        target.addClass("ui_layout");
        var _addPal = function (target) {
            target.children("div").each(function () {
                var palOpts = $.extend({}, $.fn.uiLayout.paneldefaults, $(this).parseUIConfig());
                if ("top,bottom,right,left,center".indexOf(palOpts.region) >= 0) {
                    _addPanel(target, palOpts, this);
                }
            });
        };
        target.children("form").length ? _addPal(target.children("form")) : _addPal(target);
        target.append("<div class=\"ui_layout_split_proxy_h\"></div><div class=\"ui_layout_split_proxy_v\"></div>");
        target.bind("_resize", function () {
            var opts = $.data(target[0], _cacheName).options;
            if (opts.autoFit == true) {
                _resize(target);
            }
        });
    };

    var _collapsePanels = function (target) {
        var panels = $.data(target[0], _cacheName).panels;
        if (panels.right.length > 0 && panels.right.uiPanel("options").collapsed) {
            _collapsePanel(target, pal_region.right, 0);
        }
        if (panels.left.length > 0 && panels.left.uiPanel("options").collapsed) {
            _collapsePanel(target, pal_region.left, 0);
        }
        if (panels.top.length > 0 && panels.top.uiPanel("options").collapsed) {
            _collapsePanel(target, pal_region.top, 0);
        }
        if (panels.bottom.length > 0 && panels.bottom.uiPanel("options").collapsed) {
            _collapsePanel(target, pal_region.bottom, 0);
        }
    };

    var _resize = function (target) {
        var opts = $.data(target[0], _cacheName);
        var options = opts.options;
        var pals = opts.panels;
        if (target[0].tagName == "BODY") {
            target.autoFit(true, true);
        } else {
            options.autoFit ? target.autoFit(true, true) : target.autoFit(false);
        }
        var sizeOpts = {top: 0, left: 0, width: target.width(), height: target.height()};
        _calcNS(_palVisible(pals.expandTop) ? pals.expandTop : pals.top, "n");
        _calcNS(_palVisible(pals.expandBottom) ? pals.expandBottom : pals.bottom, "s");
        _calcEW(_palVisible(pals.expandRight) ? pals.expandRight : pals.right, "e");
        _calcEW(_palVisible(pals.expandLeft) ? pals.expandLeft : pals.left, "w");
        if (_IEunder9 && !pals.center.uiPanel('options').border) {
            sizeOpts.width += 4;
            sizeOpts.height += 4;
        }
        pals.center.each(function () {
            $(this).uiPanel("resize", sizeOpts);
        });
        function _getPalHeight(pal) {
            var pal_opts = pal.uiPanel("options");
            return Math.min(Math.max(pal_opts.height||pal.outerHeight(), pal_opts.minHeight||0), pal_opts.maxHeight);
        }

        function _getPalWidth(pal) {
            var pal_opts = pal.uiPanel("options");
            return Math.min(Math.max(pal_opts.width||pal.outerWidth(), pal_opts.minWidth||0), pal_opts.maxWidth);
        }

        function _calcNS(pal, dir) {
            if (!pal.length || !_palVisible(pal)) {
                return;
            }
            var opts = pal.uiPanel("options");
            var height = _getPalHeight(pal);
            var top = (dir == "n" ? 0 : target.height() - height);
            pal.uiPanel("resize", {width: target.width(), height: height, left: 0, top: top});
            sizeOpts.height -= height;
            if (dir == "n") {
                sizeOpts.top += height;
                if (!opts.split && opts.border) {
                    sizeOpts.top -= 1;
                }
            }
            if (!opts.split && opts.border) {
                sizeOpts.height += 1;
            }
        }

        function _calcEW(pal, dir) {
            if (!pal.length || !_palVisible(pal)) {
                return;
            }
            var opts = pal.uiPanel("options");
            var width = _getPalWidth(pal);
            var left = (dir == "e" ? target.width() - width : 0);
            pal.uiPanel("resize", {width: width, height: sizeOpts.height, left: left, top: sizeOpts.top});
            sizeOpts.width -= width;
            if (dir == "w") {
                sizeOpts.left += width;
                if (!opts.split && opts.border) {
                    sizeOpts.left -= 1;
                }
            }
            if (!opts.split && opts.border) {
                sizeOpts.width += 1;
            }
        }
    };

    var _addPanel = function (target, palOptions, panel) {
        palOptions.region = palOptions.region || pal_region.center;
        var panels = $.data(target[0], _cacheName).panels;
        var region = palOptions.region;
        if (panels[region].length) {
            return;
        }
        var pal = $(panel);
        if (!pal.length) {
            pal = $("<div></div>").appendTo(target);
        }
        var palOpts = $.extend({}, $.fn.uiLayout.paneldefaults, {
            width: (pal.length ? parseInt(pal[0].style.width) || pal.width() : "auto"),
            height: (pal.length ? parseInt(pal[0].style.height) || pal.height() : "auto"),
            collapsible: true
        }, palOptions);
        palOpts = $.extend(palOpts, {
            onOpen: function () {
                var toolbar = $(this).uiPanel("toolbar").empty();
                var btnDir = {top: "up", bottom: "down", right: "right", left: "left"};
                if (!btnDir[region]) {
                    return;
                }
                var btnClass = "ui_layout_btn_" + btnDir[region];
                var btn = toolbar.children("." + btnClass);
                if (!btn.length) {
                    btn = $('<a href="javascript:void(0)"></a>').addClass('ui_layout_btn').addClass(btnClass).appendTo(toolbar);
                    btn.bind("click", {dir: region}, function (e) {
                        _collapsePanel(target, e.data.dir);
                        return false;
                    });
                }
                $(this).uiPanel("options").collapsible ? btn.show() : btn.hide();
            }
        });
        pal.uiPanel(palOpts);
        pal.addClass('ui_layout_panel ui_layout_panel_' + region);
        panels[region] = pal;
        if (pal.uiPanel("options").split) {
            pal = pal.uiPanel("panel");
            pal.addClass("ui_layout_split_" + region);
            pal.uiPanel('content').addClass("ui_layout_split_content_" + region);
            var dir = '';
            switch (region) {
                case pal_region.top:
                    dir = 's';
                    break;
                case pal_region.bottom:
                    dir = 'n';
                    break;
                case pal_region.right:
                    dir = 'w';
                    break;
                case pal_region.left:
                    dir = 'e';
                    break;
            }
            var split_proxy;
            pal.resizable($.extend({}, {
                handles: dir,
                onStartResize: function (e) {
                    _resizing = true;
                    if (region == pal_region.top || region == pal_region.bottom) {
                        split_proxy = target.children('div.ui_layout_split_proxy_v');
                    } else {
                        split_proxy = target.children('div.ui_layout_split_proxy_h');
                    }
                    var mask = $.uiMask.show({container: target, maskID: 'layout'});
                    var pos = {
                        display: 'block',
                        top: 0,
                        left: 0,
                        width: 0,
                        height: 0,
                        zIndex: parseInt(mask.css('zIndex')) + 1
                    };
                    switch (region) {
                        case pal_region.top:
                            pos.top = parseInt(pal.css('top')) + pal.outerHeight() - split_proxy.height();
                            pos.left = parseInt(pal.css('left'));
                            pos.width = pal.width();
                            pos.height = split_proxy.height();
                            break;
                        case pal_region.bottom:
                            pos.top = parseInt(pal.css('top'));
                            pos.left = parseInt(pal.css('left'));
                            pos.width = pal.width();
                            pos.height = split_proxy.height();
                            break;
                        case pal_region.right:
                            pos.top = parseInt(pal.css('top')) || 0;
                            pos.left = parseInt(pal.css('left')) || 0;
                            pos.width = split_proxy.width();
                            pos.height = pal.height();
                            break;
                        case pal_region.left:
                            pos.top = parseInt(pal.css('top')) || 0;
                            pos.left = pal.outerWidth() - split_proxy.width();
                            pos.width = split_proxy.width();
                            pos.height = pal.height();
                            break;
                    }
                    split_proxy.css(pos);
                },
                onResize: function (e) {
                    if (region == pal_region.top || region == pal_region.bottom) {
                        split_proxy.css('top', e.pageY - $(target).offset().top - split_proxy.height() / 2);
                    } else {
                        split_proxy.css('left', e.pageX - $(target).offset().left - split_proxy.width() / 2);
                    }
                    return false;
                },
                onStopResize: function (e) {
                    split_proxy.hide();
                    split_proxy = null;
                    pal.uiPanel('resize', e.data);
                    _resize(target);
                    _resizing = false;
                    $.uiMask.remove({container: target, maskID: 'layout'});
                }
            }, palOptions));
        }
    };

    function _remove(target, region) {
        var panels = $.data(target[0], _cacheName).panels;
        if (panels[region].length > 0) {
            panels[region].panel('destroy');
            panels[region] = $();
            var expandPalName = 'expand' + region.substring(0, 1).toUpperCase() + region.substring(1);
            if (panels[expandPalName]) {
                panels[expandPalName].panel('destroy');
                panels[expandPalName] = undefined;
            }
        }
    }
    /**
     *
     * @param target
     * @param region
     * @param duration 默认值: 'normal'， 三种预定速度的字符串('slow', 'normal', 或 'fast')或表示动画时长的毫秒数值(如：1000)
     * @private
     */
    var _collapsePanel = function (target, region, duration) {
        if (duration == undefined) {
            duration = 'normal';
        }
        var panels = $.data(target[0], _cacheName).panels;
        var pal = panels[region];
        var pal_opts = pal.uiPanel('options');
        if (pal_opts.onBeforeCollapse.call(pal) == false) {
            return;
        }
        var expandPalName = 'expand' + region.substring(0, 1).toUpperCase() + region.substring(1);
        if (!panels[expandPalName]) {
            panels[expandPalName] = _createPanel(pal_opts, region);
            panels[expandPalName].uiPanel('panel').bind('click', function () {
                var colPalOpts = coll_Opts();
                pal.uiPanel('open').uiPanel('expand', false).uiPanel('resize', colPalOpts.collapse);
                pal.uiPanel('panel').animate(colPalOpts.expand, function () {
                    $(this).unbind('.layout').bind('mouseleave.layout', {region: region}, function (e) {
                        if (_resizing == true) {
                            return;
                        }
                        _collapsePanel(target, e.data.region);
                    });
                });
            });
        }
        var colPalOpts = coll_Opts();
        if (!_palVisible(panels[expandPalName])) {
            panels.center.uiPanel('resize', colPalOpts.resizeC);
        }
        pal.uiPanel('panel').animate(colPalOpts.collapse, duration, function () {
            pal.uiPanel('close').uiPanel('collapse', false);
            panels[expandPalName].uiPanel('open').uiPanel('resize', colPalOpts.expandP);
            $(this).unbind('.layout');
        });
        function _createPanel(pal_opts, region) {
            var btnCollapse;
            var title = '';
            var icon = '';
            switch (region) {
                case pal_region.right:
                    btnCollapse = 'ui_layout_btn_left1';
                    break;
                case pal_region.left:
                    btnCollapse = 'ui_layout_btn_right1';
                    break;
                case pal_region.top:
                    title = pal_opts.title;
                    icon = pal_opts.icon;
                    btnCollapse = 'ui_layout_btn_down1';
                    break;
                case pal_region.bottom:
                    title = pal_opts.title;
                    icon = pal_opts.icon;
                    btnCollapse = 'ui_layout_btn_up1';
                    break;
            }
            var collPal = $('<div></div>').appendTo(target);
            collPal.uiPanel($.extend({}, $.fn.uiLayout.paneldefaults,
                {title: title, icon: icon, closed: true, minWidth: 0, minHeight: 0}));
            var pal_toolbar = collPal.uiPanel('toolbar').empty();
            var btn = pal_toolbar.children('.' + btnCollapse);
            if (!btn.length) {
                btn = $('<a href="javascript:void(0)"></a>').addClass('ui_layout_btn').addClass(btnCollapse).appendTo(pal_toolbar);
                btn.bind('click', {dir: region}, function (e) {
                    _expandPanel(target, region);
                    return false;
                });
            }
            collPal.addClass('ui_layout_expand ui_layout_expand_' + region);
            if (region == pal_region.left || region == pal_region.right) {
                var collPal_content = collPal.uiPanel('content');
                collPal_content.html('<div class="ui_layout_expand_title"><div class="icon icon_' + pal_opts.icon + '"></div>' + pal_opts.title + '</div>');
            } else {
                collPal.uiPanel('title').css('color', 'black');
            }
            collPal.uiPanel('panel').hover(function () {
                $(this).addClass('ui_layout_expand_over');
            }, function () {
                $(this).removeClass('ui_layout_expand_over');
            });
            return collPal;
        }

        function coll_Opts() {
            var centerPal_Opts = panels.center.uiPanel('options');
            var pal_collSize = pal_opts.collapsedSize;
            switch (region) {
                case pal_region.right:
                    var centerWidth = centerPal_Opts.width + pal_opts.width - pal_collSize;
                    if (pal_opts.split) {
                        centerWidth++;
                    }
                    return {
                        resizeC: {width: centerWidth},
                        expand: {left: target.width() - pal_opts.width},
                        expandP: {
                            top: centerPal_Opts.top,
                            left: target.width() - pal_collSize,
                            width: pal_collSize,
                            height: centerPal_Opts.height
                        },
                        collapse: {left: target.width(), top: centerPal_Opts.top, height: centerPal_Opts.height}
                    };
                    break;
                case pal_region.left:
                    var centerWidth = centerPal_Opts.width + pal_opts.width - pal_collSize;
                    if (pal_opts.split || !pal_opts.border) {
                        centerWidth++;
                    }
                    return {
                        resizeC: {width: centerWidth, left: pal_collSize - 1},
                        expand: {left: 0},
                        expandP: {left: 0, top: centerPal_Opts.top, width: pal_collSize, height: centerPal_Opts.height},
                        collapse: {left: -pal_opts.width, top: centerPal_Opts.top, height: centerPal_Opts.height}
                    };
                    break;
                case pal_region.top:
                    var centerHeight = centerPal_Opts.height;
                    if (!_palVisible(panels.expandTop)) {
                        centerHeight += pal_opts.height - pal_collSize + ((pal_opts.split || !pal_opts.border) ? 1 : 0);
                    }
                    panels.right.add(panels.left).add(panels.expandRight).add(panels.expandLeft).each(function () {
                        $(this).uiPanel('resize', {top: pal_collSize - 1, height: centerHeight});
                    });
                    return {
                        resizeC: {top: pal_collSize - 1, height: centerHeight},
                        expand: {top: 0}, expandP: {top: 0, left: 0, width: target.width(), height: pal_collSize},
                        collapse: {top: -pal_opts.height, width: target.width()}
                    };
                    break;
                case pal_region.bottom:
                    var centerHeight = centerPal_Opts.height;
                    if (!_palVisible(panels.expandBottom)) {
                        centerHeight += pal_opts.height - pal_collSize + ((pal_opts.split || !pal_opts.border) ? 1 : 0);
                    }
                    panels.right.add(panels.left).add(panels.expandRight).add(panels.expandLeft).each(function () {
                        $(this).uiPanel('resize', {height: centerHeight});
                    });
                    return {
                        resizeC: {height: centerHeight},
                        expand: {top: target.height() - pal_opts.height},
                        expandP: {
                            top: target.height() - pal_collSize,
                            left: 0,
                            width: target.width(),
                            height: pal_collSize
                        },
                        collapse: {top: target.height(), width: target.width()}
                    };
                    break;
            }
        }
    };
    var _expandPanel = function (target, region) {
        var panels = $.data(target[0], _cacheName).panels;
        var panel = panels[region];
        var pal_opts = panel.uiPanel('options');
        if (pal_opts.onBeforeExpand.call(panel) === false) {
            return;
        }
        var palOpts = setPalOptions();
        var expandPalName = 'expand' + region.substring(0, 1).toUpperCase() + region.substring(1);
        if (panels[expandPalName]) {
            panels[expandPalName].uiPanel('close');
            panel.uiPanel('panel').stop(true, true);
            panel.uiPanel('open').uiPanel('expand', false).uiPanel('resize', palOpts.collapse);
            panel.uiPanel('panel').animate(palOpts.expand, function () {
                _resize(target);
            });
        }

        function setPalOptions() {
            var cPal_opts = panels.center.uiPanel('options');
            if (region == pal_region.right && panels.expandRight) {
                return {
                    collapse: {left: target.width(), top: cPal_opts.top, height: cPal_opts.height},
                    expand: {left: target.width() - panels[pal_region.right].uiPanel('options').width}
                };
            } else {
                if (region == pal_region.left && panels.expandLeft) {
                    return {
                        collapse: {
                            left: -panels[pal_region.left].uiPanel('options').width,
                            top: cPal_opts.top,
                            height: cPal_opts.height
                        },
                        expand: {left: 0}
                    };
                } else {
                    if (region == pal_region.top && panels.expandTop) {
                        return {
                            collapse: {top: -panels[pal_region.top].uiPanel('options').height, width: target.width()},
                            expand: {top: 0}
                        };
                    } else {
                        if (region == pal_region.bottom && panels.expandBottom) {
                            return {
                                collapse: {top: target.height(), width: target.width()},
                                expand: {top: target.height() - panels[pal_region.bottom].uiPanel('options').height}
                            };
                        }
                    }
                }
            }
        }
    };

    var _palVisible = function (uiPanel) {
        if (!uiPanel) {
            return false;
        }
        if (uiPanel.length > 0) {
            return uiPanel.attr('closed') == 'false';
        } else {
            return false;
        }
    };
})(jQuery);
